<template>
  <el-scrollbar
    :height="height"
    @scroll="scrollChange"
    ref="scrollMoreRef"
    class="el-scrollbar-box"
    :max-height="maxHeight"
  >
    <!-- 滚动内容插槽 -->
    <slot></slot>

    <!-- 底部加载字样 -->
    <div class="scroll-more-bottom-title f-j-a-c" v-if="showMoreTitle">
      <span v-show="moreLoading && !noMore">加载中...</span>
      <span v-show="noMore">没有更多了~</span>
    </div>

    <!-- 返回顶部按钮 -->
    <div
      class="back-top-box"
      :class="{ 'svg-icon-show': showTop }"
      @click.stop="showTop ? setScrllTop(0) : ''"
    >
      <svg-icon class="svg-icon" name="icon-fhdb-bai"></svg-icon>
    </div>
  </el-scrollbar>
</template>
<script>
import { defineComponent, ref, reactive, toRefs, onMounted } from "vue";
export default defineComponent({
  props: {
    height: {
      type: [String],
      default: "100%",
    },
    maxHeight:{
      type: [String],
      default: "100%",
    },
    delay: {
      type: Number,
      default: 200,
    }, //节流时延
    distance: {
      type: Number,
      default: 100,
    }, //触底阈值
    immediate: {
      type: Boolean,
      default: false,
    }, //挂载后手动执行一次加载方法
    load: {
      type: Function,
      default: () => {},
    }, //加载数据方法
    noMore: {
      type: Boolean,
      default: false,
    }, //是否还有更多数据
    showMoreTitle: {
      type: Boolean,
      default: true,
    }, //是否显示底部文字
    hasToTopIcon: {
      type: Boolean,
      default: true,
    }, //是否需要返回顶部按钮
  },
  setup(props, { attrs, slots, emit }) {
    let scrollMoreRef = ref(null);
    let data = reactive({
      moreLoading: false,
      showTop: false, //返回顶部按钮显示隐藏
    });
    let timer = null;
    // 监听滚动
    let scrollChange = (e) => {
      clearTimeout(timer);
      timer = setTimeout(() => {
        // 设置返回顶部按钮显示隐藏(如果需要返回顶部按钮)
        if (props.hasToTopIcon) {
          e.scrollTop > 600 ? (data.showTop = true) : (data.showTop = false);
        }
        if (props.noMore) return;
        const scrollDom = scrollMoreRef.value.wrapRef;
        const scrollClientHeight = scrollDom.clientHeight; //scroll视图高
        const scrollHeight = scrollDom.scrollHeight; //包裹总高度
        // 如果滚动高度 + 视图高度 + 触底阈值 >= 子元素总高度 视为触底
        if (
          e.scrollTop + scrollClientHeight + props.distance >= scrollHeight &&
          !data.moreLoading
        ) {
          try {
            data.moreLoading = true;
            props.load(true);
          } finally {
            setTimeout(() => {
              data.moreLoading = false;
            }, props.distance);
          }
        }
      }, props.delay);
    };

    // 设置滚动条距离
    let setScrllTop = (top) => {
      scrollMoreRef.value.setScrollTop(top);
      scrollMoreRef.value.update();
    };

    onMounted(() => {
      // 如果需要页面挂载自动执行一次 则调用加载方法
      if (props.immediate) {
        props.load();
      }
    });

    return {
      setScrllTop,
      ...toRefs(data),
      scrollChange,
      scrollMoreRef,
    };
  },
});
</script>

<style lang="scss" scoped>
.el-scrollbar-box {
  position: relative;
}

// 更多文字
.scroll-more-bottom-title {
  font-size: 14px;
  color: #656f79;
  height: 32px;
}

// 返回顶部
.back-top-box {
  position: absolute;
  right: 20px;
  bottom: 30px;
  transition: opacity 0.3s;
  opacity: 0;
  .svg-icon {
    width: 50px;
    height: 50px;
  }
}

// 显示显示
.svg-icon-show {
  opacity: 1;
  cursor: pointer;
}
</style>
